package jwcb.javapjframework.ms_template.service.service;

import com.fasterxml.jackson.core.type.TypeReference;
import jwcb.javapjframework.common.redis.RedisService.service.RedisService;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class RedisHashTestService {

    @Autowired
    private RedisService redisService;

    private static final String TEST_KEY = "test:hash:operations";
    private static final String USER_KEY = "user";
    private static final String PRODUCT_KEY = "product";
    private static final String ORDER_KEY = "order";

    public String testRedisHashOperations() {
        StringBuilder result = new StringBuilder();
        result.append("Redis Hash 操作测试开始...\n\n");

        try {
            // 清理旧数据
            redisService.deleteObject(TEST_KEY);
            
            // 1. 缓存整个Map测试
            Map<String, String> testMap = new HashMap<>();
            testMap.put("name", "John");
            testMap.put("age", "30");
            testMap.put("city", "New York");
            
            redisService.setCacheMap(TEST_KEY, testMap);
            Map<String, String> cachedMap = redisService.getCacheMap(TEST_KEY, new TypeReference<Map<String, String>>() {});
            
            result.append("测试1: 缓存整个Map\n")
                  .append("预期: {name=John, age=30, city=New York}, 实际: ").append(cachedMap).append("\n")
                  .append("结果: ").append(cachedMap.equals(testMap) ? "成功" : "失败").append("\n\n");

            // 2. 插入单个数据测试
            redisService.setCacheMapValue(TEST_KEY, "email", "john@example.com");
            String email = redisService.getCacheMapValue(TEST_KEY, "email",String.class);
            
            result.append("测试2: 插入单个数据\n")
                  .append("预期: john@example.com, 实际: ").append(email).append("\n")
                  .append("结果: ").append("john@example.com".equals(email) ? "成功" : "失败").append("\n\n");

            // 3. 复杂对象测试
            Map<String, User> userMap = new HashMap<>();
            userMap.put("user1", new User(1, "Alice"));
            userMap.put("user2", new User(2, "Bob"));
            
            redisService.setCacheMap(USER_KEY, userMap);
            Map<String, User> cachedUserMap = redisService.getCacheMap(USER_KEY, new TypeReference<Map<String, User>>() {});
            
            result.append("测试3: 复杂对象Map\n")
                  .append("预期: {user1=User{id=1, name='Alice'}, user2=User{id=2, name='Bob'}}, 实际: ").append(cachedUserMap).append("\n")
                  .append("结果: ").append(cachedUserMap.size() == 2 && 
                         cachedUserMap.get("user1").getName().equals("Alice") ? "成功" : "失败").append("\n\n");

            // 4. 获取单个数据测试
            User user1 = redisService.getCacheMapValue(USER_KEY, "user1",User.class);
            
            result.append("测试4: 获取单个数据\n")
                  .append("预期: User{id=1, name='Alice'}, 实际: ").append(user1).append("\n")
                  .append("结果: ").append(user1 != null && user1.getId() == 1 && "Alice".equals(user1.getName()) ? "成功" : "失败").append("\n\n");

            // 5. 获取多个数据测试
            List<Object> keys = Arrays.asList("user1", "user2", "user3");
            List<User> users = redisService.getMultiCacheMapValue(USER_KEY, keys, new TypeReference<List<User>>() {});
            
            result.append("测试5: 获取多个数据\n")
                  .append("预期: [User{id=1, name='Alice'}, User{id=2, name='Bob'}, null], 实际: ").append(users).append("\n")
                  .append("结果: ").append(users.size() == 3 && 
                         users.get(0).getName().equals("Alice") && 
                         users.get(1).getName().equals("Bob") && 
                         users.get(2) == null ? "成功" : "失败").append("\n\n");

            // 6. 删除单个数据测试
            redisService.deleteCacheMapValue(USER_KEY, "user2");
            Map<String, User> afterDelete = redisService.getCacheMap(USER_KEY, new TypeReference<Map<String, User>>() {});
            
            result.append("测试6: 删除单个数据\n")
                  .append("预期: {user1=User{id=1, name='Alice'}}, 实际: ").append(afterDelete).append("\n")
                  .append("结果: ").append(afterDelete.size() == 1 && afterDelete.containsKey("user1") ? "成功" : "失败").append("\n\n");

            // 7. 更新数据测试
            redisService.setCacheMapValue(USER_KEY, "user1", new User(1, "Alice Updated"));
            User updatedUser = redisService.getCacheMapValue(USER_KEY, "user1",User.class);
            
            result.append("测试7: 更新数据\n")
                  .append("预期: Alice Updated, 实际: ").append(updatedUser.getName()).append("\n")
                  .append("结果: ").append("Alice Updated".equals(updatedUser.getName()) ? "成功" : "失败").append("\n\n");

            // 8. 空值处理测试
            redisService.setCacheMapValue(TEST_KEY, "empty", null);
            Object emptyValue = redisService.getCacheMapValue(TEST_KEY, "empty",Object.class);
            
            result.append("测试8: 空值处理\n")
                  .append("预期: null, 实际: ").append(emptyValue).append("\n")
                  .append("结果: ").append(emptyValue == null ? "成功" : "失败").append("\n\n");

            // 9. 批量操作性能测试
            Map<String, String> largeMap = new HashMap<>();
            for (int i = 0; i < 1000; i++) {
                largeMap.put("key_" + i, "value_" + i);
            }
            
            long startTime = System.currentTimeMillis();
            redisService.setCacheMap(PRODUCT_KEY, largeMap);
            long putAllTime = System.currentTimeMillis() - startTime;
            
            startTime = System.currentTimeMillis();
            Map<String, String> retrievedMap = redisService.getCacheMap(PRODUCT_KEY, new TypeReference<Map<String, String>>() {});
            long getAllTime = System.currentTimeMillis() - startTime;
            
            result.append("测试9: 批量操作性能\n")
                  .append("批量写入耗时: ").append(putAllTime).append("ms\n")
                  .append("批量读取耗时: ").append(getAllTime).append("ms\n")
                  .append("结果: ").append(retrievedMap.size() == 1000 ? "成功" : "失败").append("\n\n");

            // 10. 复杂嵌套类型测试
            Map<String, Map<String, User>> nestedMap = new HashMap<>();
            Map<String, User> teamA = new HashMap<>();
            teamA.put("member1", new User(101, "Tom"));
            teamA.put("member2", new User(102, "Jerry"));
            
            Map<String, User> teamB = new HashMap<>();
            teamB.put("member1", new User(201, "Mike"));
            
            nestedMap.put("teamA", teamA);
            nestedMap.put("teamB", teamB);
            
            redisService.setCacheMap(ORDER_KEY, nestedMap);
            Map<String, Map<String, User>> cachedNestedMap = redisService.getCacheMap(ORDER_KEY, 
                new TypeReference<Map<String, Map<String, User>>>() {});
            
            boolean nestedSuccess = cachedNestedMap != null &&
                   cachedNestedMap.get("teamA").size() == 2 &&
                   "Tom".equals(cachedNestedMap.get("teamA").get("member1").getName());
            
            result.append("测试10: 复杂嵌套类型\n")
                  .append("预期: 2层嵌套Map, 实际: ").append(cachedNestedMap).append("\n")
                  .append("结果: ").append(nestedSuccess ? "成功" : "失败").append("\n\n");

            result.append("✅ 所有Hash操作测试完成!");

        } catch (Exception e) {
            result.append("\n❌ 测试异常: ").append(e.getMessage());
            e.printStackTrace();
        } finally {
            // 清理测试数据
            redisService.deleteObject(TEST_KEY);
            redisService.deleteObject(USER_KEY);
            redisService.deleteObject(PRODUCT_KEY);
            redisService.deleteObject(ORDER_KEY);
        }

        return result.toString();
    }
    
    // 测试用复杂类型
    @Setter
    @Getter
    static class User {
        // getters and setters
        private int id;
        private String name;
        
        public User() {}
        
        public User(int id, String name) {
            this.id = id;
            this.name = name;
        }

        @Override
        public String toString() {
            return "User{" + "id=" + id + ", name='" + name + '\'' + '}';
        }
    }
}